// Inspired by KF5 KColorCombo, published under LGPLv2

#include "penstylecombobox.h"

#include <QAbstractItemDelegate>
#include <QApplication>
#include <QColorDialog>
#include <QStylePainter>

class DelegateBox : public QAbstractItemDelegate
{
public:
    enum
    {
        PenStyleRole = Qt::UserRole + 1
    };

    enum LayoutMetrics
    {
        FrameMargin = 3
    };

    explicit DelegateBox(QObject *parent = 0):
        QAbstractItemDelegate(parent)
    {

    }

    virtual ~DelegateBox()
    {

    }

    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        // highlight selected item
        QStyleOptionViewItem opt(option);
        opt.showDecorationSelected = true;
        QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
        style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
        QRect frame = option.rect.adjusted(FrameMargin, FrameMargin, -FrameMargin, -FrameMargin);

        // Pen style
        painter->setPen(Qt::transparent);
        painter->setBrush(QBrush(option.palette.base()));
        painter->setRenderHint(QPainter::Antialiasing, false);
        painter->drawRoundedRect(frame, 2, 2);
        painter->setPen(QPen(option.palette.text(), 0, index.data(PenStyleRole).value<Qt::PenStyle>()));
        painter->setBrush(Qt::NoBrush);
        painter->drawLine(frame.left() + 2, frame.center().y(), frame.right() - 2, frame.center().y());
        painter->setPen(QPen(option.palette.text(), 0, Qt::SolidLine));
        painter->drawRoundedRect(frame, 2, 2);
    }

    virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        Q_UNUSED(index)

        // the width does not matter, as the view will always use the maximum width available
        return QSize(100, option.fontMetrics.height() + 2 * FrameMargin);
    }
};

PenStyleComboBox::PenStyleComboBox(QWidget *parent):
    QComboBox(parent)
{
    setItemDelegate(new DelegateBox(this));

    connect(this, QOverload<int>::of(&QComboBox::activated),
            this, &PenStyleComboBox::onActivated);
    connect(this, QOverload<int>::of(&QComboBox::highlighted),
            this, &PenStyleComboBox::onHighlighted);
    connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &PenStyleComboBox::onCurrentIndexChanged);
}

PenStyleComboBox::~PenStyleComboBox()
{

}

void PenStyleComboBox::setCurrentPenStyle(Qt::PenStyle style)
{
    setCurrentIndex(m_penStyleList.indexOf(style));
}

Qt::PenStyle PenStyleComboBox::currentPenStyle() const
{
    return m_penStyleList.value(currentIndex());
}

void PenStyleComboBox::setPenStyles(const QList<Qt::PenStyle> &styles)
{
    clear();
    m_penStyleList = styles;
    for (int i=0; i<m_penStyleList.count(); i++)
    {
        addItem(QString());
        setItemData(i, QVariant::fromValue<Qt::PenStyle>(m_penStyleList.value(i)), DelegateBox::PenStyleRole);
    }
}

QList<Qt::PenStyle> PenStyleComboBox::penStyles() const
{
    return m_penStyleList;
}

void PenStyleComboBox::onActivated(int index)
{
    emit activated(m_penStyleList.value(index));
}

void PenStyleComboBox::onHighlighted(int index)
{
    m_paintedPenStyle = m_penStyleList.value(index);
    emit highlighted(m_paintedPenStyle);
}

void PenStyleComboBox::onCurrentIndexChanged(int index)
{
    m_paintedPenStyle = m_penStyleList.value(index);
    emit currentPenStyleChanged(m_paintedPenStyle);
}

void PenStyleComboBox::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    QStylePainter painter(this);
    painter.setPen(palette().color(QPalette::Text));

    QStyleOptionComboBox option;
    initStyleOption(&option);
    painter.drawComplexControl(QStyle::CC_ComboBox, option);

    QRect frame = style()->subControlRect(QStyle::CC_ComboBox, &option,
                                          QStyle::SC_ComboBoxEditField, this).adjusted(1, 1, -1, -1);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(Qt::transparent);
    painter.setBrush(QBrush(option.palette.base()));
    painter.drawRoundedRect(frame, 2, 2);
    painter.setRenderHint(QPainter::Antialiasing, false);
    painter.setPen(QPen(option.palette.text(), 0, m_paintedPenStyle));
    painter.setBrush(Qt::NoBrush);
    painter.drawLine(frame.left() + 2, frame.center().y(), frame.right() - 2, frame.center().y());
    painter.setPen(QPen(option.palette.text(), 0, Qt::SolidLine));
    painter.drawRoundedRect(frame, 2, 2);
}
